﻿namespace TvUtil
{

	#region Using

	using System;
	using System.Collections.Generic;
	using System.Text;
	using System.Net;
	using System.IO;
	using System.Windows.Forms;
	using System.Xml.Serialization;
	using System.Xml;

	#endregion Using

	/// <summary>
	/// Třída televizní stanice
	/// </summary>
	[Serializable]
	public sealed class ProgramStation
	{

		#region Members

		private List<ProgramShow> m_programShows;
		private string m_name;
		private DateTime m_date;

		private static string _cacheFileName = @"TvNotify\TvNotifierCache-{0}.XML";

		#endregion Members

		#region Constructor

		/// <summary>
		/// Bezparametrický konstruktor
		/// </summary>
		private ProgramStation()
		{
			this.m_programShows = new List<ProgramShow>();
		}

		/// <summary>
		/// Privátní konstruktor
		/// </summary>
		/// <param name="name">Název televizní stanice</param>
		private ProgramStation(string name)
			: this()
		{
			this.m_name = name;
		}

		#endregion Constructor

		#region Properties

		/// <summary>
		/// Seznam televizních show
		/// </summary>
		[XmlElement]
		public List<ProgramShow> Shows
		{
			get
			{
				return this.m_programShows;
			}
		}

		/// <summary>
		/// Berlička pro serializaci
		/// </summary>
		[XmlAttribute]
		public string Date
		{
			get
			{
				return this.m_date.ToShortDateString();
			}
			set
			{
				this.m_date = DateTime.Parse(value);
			}
		}

		/// <summary>
		/// Nastaví či získá název televizní stanice
		/// </summary>
		[XmlAttribute]
		public string Name
		{
			get
			{
				return this.m_name;
			}
			set
			{
				this.m_name = value;
			}
		}

		#endregion Properties

		#region Methods

		/// <summary>
		/// Metoda serializuje seznam televizních stanic a jejich programů do XML
		/// </summary>
		/// <param name="stations"><see cref="List"/></param>
		private static void Save(List<ProgramStation> stations, DateTime date)
		{
			if (stations.Count == 0)
				return;
			string d = string.Format("{0}-{1}-{2}", date.Day,date.Month, date.Year);
			string fileName = Path.Combine(Environment.GetFolderPath(
				Environment.SpecialFolder.ApplicationData), string.Format(_cacheFileName, d));
			string dir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"TvNotify");
			if (!Directory.Exists(dir))
			{
				Directory.CreateDirectory(dir);
			}
			using(XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.Default))
			{
				XmlSerializer serializer = new XmlSerializer(typeof(List<ProgramStation>));
				serializer.Serialize(writer, stations);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="stations"></param>
		/// <param name="date"></param>
		/// <returns></returns>
		private static bool TryCache(List<ProgramStation> stations, DateTime date)
		{
			string d = string.Format("{0}-{1}-{2}", date.Day, date.Month, date.Year);
			string fileName = Path.Combine(Environment.GetFolderPath(
				Environment.SpecialFolder.ApplicationData), string.Format(_cacheFileName, d));
			if (!File.Exists(fileName))
				return false;

			using (XmlTextReader reader = new XmlTextReader(fileName))
			{
				XmlSerializer serializer = new XmlSerializer(typeof(List<ProgramStation>));
				List<ProgramStation> st = serializer.Deserialize(reader) as List<ProgramStation>;
				stations.AddRange(st.ToArray());
			}
			return true;
		}

		/// <summary>
		/// Metoda načte kolekci televizních stanicí k datu <paramref name="date"/>
		/// </summary>
		/// <param name="date"><see cref="DateTime"/></param>
		/// <returns><see cref="ProgramStation"/></returns>
		public static ProgramStation[] Create(DateTime date)
		{
			TimeSpan ts = (
				new DateTime(date.Year, date.Month, date.Day, 0, 0, 0).ToUniversalTime() -
				new DateTime(1970, 1, 1, 0, 0, 0));
			long unixTime = (long)ts.TotalSeconds;

			List<ProgramStation> stations = new List<ProgramStation>();
			// Zkoušíme hledat v cache
			if (TryCache(stations, date))
			{
				return stations.ToArray();
			}
			try
			{
				WebRequest request = WebRequest.Create(string.Format(
					"http://www.denpodni.cz/tvprogram/index.php?action=vytvor&prg[]=1&prg[]=2&prg[]=3&prg[]=4&bookmark=2&txt=1&nazev=tvprogram&nazevpalm=Program+TV&dny[]={0}", unixTime));
				WebResponse response = request.GetResponse();
				using (Stream stream = response.GetResponseStream())
				using (TextReader reader = new StreamReader(stream, Encoding.Default))
				{
					string content = reader.ReadToEnd();
					string[] lines = content.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
					int index = 0;
					while (index < lines.Length)
					{
						if (index + 2 > lines.Length)
							break;
						string[] first = lines[index].Split(new char[] { ' ' });
						ProgramStation station = new ProgramStation(first[first.Length-1]);
						stations.Add(station);
						index += 2;
						for (int i = index; i < lines.Length; ++i)
						{
							// Detekce konce programu pro aktuální stanici
							if (lines[i].Length < 3)
							{
								index = i + 1;
								break;
							}
							// Získáme čas, název
							string[] columns = lines[i].Split(new char[] { '\t' });
							station.Shows.Add(new ProgramShow(columns[0], columns[1]));
						}
					}
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
				Application.Exit();
			}
			Save(stations, date);
			return stations.ToArray();
		}


		#endregion Methods

	}
}
